#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/sysinfo.h>
#include <sys/socket.h>

#include "MainProc.h"
#include "MemPool.h"
#include "Server.h"
#include "SvrMgr.h"
#include "BufMgr.h"

#define BLOCK_MAX_SIZE 1448
#define BLOCK_MAX_LEVEL 20

CMainProc::CMainProc()
{
    m_pMemPool = nullptr;
    m_pSvrMgr = nullptr;
    m_pBufMgr = nullptr;
    m_pThrdId = nullptr;
    m_nCore = 0;
}

CMainProc::~CMainProc()
{
    Destroy();
}

bool CMainProc::Init()
{
    int ifd = -1;
    CMemPool *mp = nullptr;

    m_nCore = get_nprocs();
    // 创建共享内存池
    mp = CMemPool::GetInstance();

    if (nullptr == mp)
        return false;

    if (!mp->Initialize(BLOCK_MAX_SIZE, BLOCK_MAX_LEVEL))
    {
        mp->Destroy();
        return false;
    }

    m_pMemPool = mp;
    m_pBufMgr = CBufMgr::GetInstance();

    if (nullptr == m_pBufMgr)
        goto FailedLabel;

    if (!m_pBufMgr->Init())
        goto FailedLabel;

    // 创建服务管理
    m_pSvrMgr = CSvrMgr::GetInstance();

    if (nullptr == m_pSvrMgr)
        goto FailedLabel;

    // 创建绑定监听socket
    ifd = m_pSvrMgr->CreateListenSocket();

    if (0 >= ifd)
        goto FailedLabel;

    m_pThrdId = new pthread_t[m_nCore]();

    if (nullptr == m_pThrdId)
        goto FailedLabel;

    return true;

FailedLabel:
    Destroy();
    return false;
}

bool CMainProc::Start()
{
    int iRet = 0;

    for (size_t i = 0; i < m_nCore; i++)
    {
        iRet = pthread_create(&m_pThrdId[i], nullptr, WorkerThread, this);

        if (0 != iRet)
        {
            Stop();
            return false;
        }
    }

    return true;
}

bool CMainProc::Stop()
{
    if (nullptr != m_pSvrMgr)
    {
        m_pSvrMgr->StopServer();
    }

    return true;
}

void CMainProc::Destroy()
{
    if (nullptr != m_pThrdId)
    {
        for (size_t i = 0; i < m_nCore; i++)
        {
            if (0 != m_pThrdId[i])
                pthread_join(m_pThrdId[i], nullptr);
        }

        delete[] m_pThrdId;
        m_pThrdId = nullptr;
    }

    if (nullptr != m_pSvrMgr)
    {
        m_pSvrMgr->CloseListenSocket();
        m_pSvrMgr->Destroy();
        delete m_pSvrMgr;
        m_pSvrMgr = nullptr;
    }

    if (nullptr != m_pBufMgr)
    {
        m_pBufMgr->Destroy();
        delete m_pBufMgr;
        m_pBufMgr = nullptr;
    }

    if (nullptr != m_pMemPool)
    {
        m_pMemPool->Destroy();
        m_pMemPool = nullptr;
    }
}

void *CMainProc::WorkerThread(void *param)
{
    CServer *pSvr = nullptr;
    CSvrMgr *pSvrMgr = CSvrMgr::GetInstance();
    ServerNode *pNode = pSvrMgr->CreateServerNode();

    if (nullptr == pNode)
        return nullptr;

    pSvr = pNode->pSvr;

    if (nullptr == pSvr)
    {
        pSvrMgr->DestroyServerNode(pNode);
        return nullptr;
    }

    pSvr->Init(pSvrMgr->GetListenSocket());
    pSvr->Start();
    pSvrMgr->DestroyServerNode(pNode);

    return nullptr;
}